﻿using General.Core.Common.OAuth.WeChat;
using General.Core.Config;
using General.Entities.Models;
using General.Framework;
using General.Mvc.Filters;
using General.Services.Admin;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

namespace General.Mvc.Controllers.Admin.Public
{
    [Route("api/admin/Public/[controller]/[action]")]
    [ApiController]
    [ServiceFilter(typeof(ResponseLogTimeFilter))]
    public class AccountController : Controller
    {
        private readonly IAdminService adminService;
        private readonly IMemoryCache memoryCache;
        private readonly ILogger logger;

        public AccountController(IAdminService adminService,
            IMemoryCache memoryCache,
            ILogger<AccountController> logger)
        {
            this.adminService = adminService;
            this.memoryCache = memoryCache;
            this.logger = logger;
        }

        /// <summary>
        /// 修改我的登录密码
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpPost]
        [ServiceFilter(typeof(AdminCheckFilter))]
        public async Task<IActionResult> EditMyPassWord([FromForm] string oldPsw, [FromForm] string newPsw)
        {
            AjaxResult result = new AjaxResult();
            var session = JsonHelper.Deserialize<tc_admin>(HttpContext.Session.GetString("Admin"));
            var user = await adminService.GetInfoById(session.id);
            if (EncryptHelper.Md5(oldPsw) != user.password)
            {
                result.code = AjaxResultStateEnum.Error;
                result.message = "修改失败！原密码错误！";
                return Content(JsonHelper.Serialize(result));
            }
            if (string.IsNullOrWhiteSpace(newPsw) || newPsw.Length < 6 || newPsw.Length > 16)
            {
                result.code = AjaxResultStateEnum.Error;
                result.message = "修改失败！请检查新密码长度！";
                return Content(JsonHelper.Serialize(result));
            }
            await adminService.UpdateUserPwd(user.id, newPsw);

            result.code = AjaxResultStateEnum.Ok;
            result.message = "修改成功！";
            return Content(JsonHelper.Serialize(result));
        }


        /// <summary>
        /// 修改我的昵称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpPost]
        [ServiceFilter(typeof(AdminCheckFilter))]
        public async Task<IActionResult> EditMyNickName([FromForm] string name)
        {
            AjaxResult result = new AjaxResult();
            if (string.IsNullOrWhiteSpace(name))
            {
                result.code = AjaxResultStateEnum.Error;
                result.message = "昵称不能为空！";
                return Content(JsonHelper.Serialize(result));
            }
            //var isExist = await adminService.GetInfoByUserName(name);
            //if (isExist!=null)
            //{
            //    result.code = AjaxResultStateEnum.Error;
            //    result.message = "此用户名已存在！";
            //    return Content(JsonHelper.Serialize(result));
            //}
            var user = JsonHelper.Deserialize<tc_admin>(HttpContext.Session.GetString("Admin"));
            await adminService.UpdateUsername(user, name);
            result.code = AjaxResultStateEnum.Ok;
            result.message = "修改成功！";
            return Content(JsonHelper.Serialize(result));
        }



        /// <summary>
        /// 微信登录生成绑定二维码
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [ServiceFilter(typeof(AdminCheckFilter))]
        public async Task<IActionResult> WeChatBindQRCode()
        {
            var redisKeyName = memoryCache.Get(GobalConfig.SYSTEM_CONFIG_UNIQUEIDENTIFICATION_STRING);
            var guid = Guid.NewGuid().ToString();
            var websiteUrl = memoryCache.Get(GobalConfig.SYSTEM_CONFIG_STRING + "Url");
            var url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatDefaults.AppId + "&redirect_uri=" + websiteUrl + "/api/admin/public/account/wechatbindin&response_type=code&scope=snsapi_userinfo&state=" + guid + "&connect_redirect=1#wechat_redirect";

            HttpContext.Response.Cookies.Append(GobalConfig.SYSTEM_WECHATUSERREDISKEY_STRING, guid, new CookieOptions
            {
                Expires = DateTime.Now.AddMinutes(20),
                Secure = true
            });
            var user = JsonHelper.Deserialize<tc_admin>(HttpContext.Session.GetString("Admin"));
            await RedisHelper.SetAsync(redisKeyName + "WeChatBind_" + guid, "0", TimeSpan.FromMinutes(10));


            var result = new AjaxResult()
            {
                code = AjaxResultStateEnum.Ok,
                message = "/api/qrcode?url=" + StringExtension.UrlEncode(url),
                data = guid
            };
            return Content(JsonHelper.Serialize(result));
        }

        /// <summary>
        /// 微信刷新登录状态
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [ServiceFilter(typeof(AdminCheckFilter))]
        public async Task<IActionResult> WeChatRefreshStatus()
        {
            var value = "";
            HttpContext.Request.Cookies.TryGetValue("WeChatBind_", out value);
            var redisKeyName = memoryCache.Get(GobalConfig.SYSTEM_CONFIG_UNIQUEIDENTIFICATION_STRING);
            var bindVal = await RedisHelper.GetAsync(redisKeyName + "WeChatBind_" + value);
            if (string.IsNullOrWhiteSpace(bindVal))
            {
                return Content(new AjaxResult().Fail("超时！请重新扫码！"));
            }
            if (bindVal == "0")
            {
                return Content(new AjaxResult().Error("请扫码！"));
            }
            else 
            {
                var user = JsonHelper.Deserialize<tc_admin>(HttpContext.Session.GetString("Admin"));
                var data = await adminService.GetInfoById(user.id);
                if (await adminService.IsHasOpenid("wechat", bindVal, user.id))
                {
                    return Content(new AjaxResult().Fail("绑定失败！该微信号已绑定过账号！"));
                }
                await adminService.BindOpenId(user.id,"wechat", bindVal);
                return Content(new AjaxResult().Ok("绑定成功！"));
            }
        }




        /// <summary>
        /// 微信跳转授权绑定
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> WeChatBindIn(string code, string state)
        {
            try
            {
                HttpContext.Response.ContentType = "text/html;charset=utf-8";
                if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(state))
                {
                    return Content("<script>alert('绑定失败')</script>");
                }

                Random random = new Random(Environment.TickCount);
                //string tokenUri = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxf1f84ee1c835dc1e&secret=a0b7f9516303199ea3fe3b39f7a930b0&code=0110XdHa1yrN4A0gojHa1kJ4ww40XdHe&state=state&grant_type=authorization_code";
                string tokenUri = WeChatDefaults.AccessTokenEndpoint
                    + "?appid=" + WeChatDefaults.AppId
                    + "&secret=" + WeChatDefaults.AppSecret
                    + "&code=" + code//code为前端传入参数，自行获取
                    + "&state=" + state
                    + "&grant_type=authorization_code";

                string resultAccessToken = ClientRequest(tokenUri, string.Empty, "POST");
                if (!string.IsNullOrEmpty(resultAccessToken))
                {
                    WeChatTocken weChatTocken1 = new WeChatTocken();
                    weChatTocken1 = JsonConvert.DeserializeObject<WeChatTocken>(resultAccessToken);
                    if (!string.IsNullOrEmpty(weChatTocken1.Access_Token))
                    {
                        string userUri = WeChatDefaults.UserInformationEndpoint
                            + "?access_token="
                            + weChatTocken1.Access_Token
                            + "&openid=" + weChatTocken1.OpenId;

                        string resultUserInfo = ClientRequest(userUri, string.Empty, "POST");
                        if (!string.IsNullOrEmpty(resultUserInfo))
                        {
                            WeChatUserInfo weChatUserInfo1 = new WeChatUserInfo();
                            weChatUserInfo1 = JsonConvert.DeserializeObject<WeChatUserInfo>(resultUserInfo);
                            if (!string.IsNullOrEmpty(weChatUserInfo1.OpenId))
                            {
                                var redisKeyName = memoryCache.Get(GobalConfig.SYSTEM_CONFIG_UNIQUEIDENTIFICATION_STRING);
                                var bindVal = await RedisHelper.GetAsync(redisKeyName + "WeChatBind_" + state);
                                if (string.IsNullOrWhiteSpace(bindVal))
                                {
                                    return Content("<script>alert('二维码过期，请重新扫码绑定！')</script>");
                                }
                                await RedisHelper.SetAsync(redisKeyName + "WeChatBind_" + state, weChatUserInfo1.OpenId, TimeSpan.FromMinutes(10));

                                return Content("<script>alert('扫码成功，请在网页中查看！')</script>");
                            }
                            else
                            {
                                return Ok("<script>alert('扫码失败，请联系网站管理员！')</script>");
                            }
                        }
                        else
                        {
                            logger.LogInformation("请求微信用户基本信息失败");
                            return Content("<script>alert('请求微信用户基本信息失败')</script>");
                        }
                    }
                    else
                    {
                        logger.LogInformation("请求access_token失败");
                        return Content("<script>alert('请求access_token失败')</script>");
                    }
                }
                return Content("<script>alert('绑定失败')</script>");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// <summary>
        /// 发送请求（get/post/http/https）
        /// </summary>
        /// <param name="uri">请求地址</param>
        /// <param name="JsonStr">json数据</param>
        /// <param name="Method">请求方式POST/GET</param>
        /// <returns></returns>
        public string ClientRequest(string uri, string JsonStr, string Method = "POST")
        {
            try
            {
                var httpRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
                httpRequest.Method = Method;
                httpRequest.ContentType = "application/json";
                if (Method.ToLower() == "get")
                {
                    httpRequest.ContentType = "application/x-www-form-urlencoded";
                }
                httpRequest.Proxy = null;
                httpRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13";
                httpRequest.Headers.Add("Accept-Language", "zh-cn,en-us;q=0.8,zh-hk;q=0.6,ja;q=0.4,zh;q=0.2");
                httpRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";

                //如果是发送HTTPS请求  
                if (uri.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    httpRequest.ProtocolVersion = HttpVersion.Version10;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                }
                else
                {
                    ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                }

                if (!string.IsNullOrEmpty(JsonStr))
                {
                    using (var dataStream = new StreamWriter(httpRequest.GetRequestStream()))
                    {
                        dataStream.Write(JsonStr);
                        dataStream.Flush();
                        dataStream.Close();
                    }
                }

                var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
                using (var dataStream = new StreamReader(httpResponse.GetResponseStream()))
                {
                    var result = dataStream.ReadToEnd();
                    return result;
                }
            }
            catch (Exception ex)
            {
                return "{\"error\":\"" + ex.Message + "\"}";
            }
        }

        private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
            //throw new NotImplementedException();
        }
    }
}
